import { Context, h, Schema, Session } from 'koishi'
import { readFileSync } from 'fs'
import { resolve } from 'path'
import {} from 'koishi-plugin-adapter-onebot';

import { Service } from 'koishi';


import { formatDate, resizeImageToBase64 } from './utils';
import { at } from '@satorijs/element/jsx-runtime';

export const inject = ['database'];

export const name = 'progressive-warn'

const pkg = JSON.parse(
  readFileSync(resolve(__dirname, '../package.json'), 'utf-8')
)

export interface Config {
  enableKoishiDbAuthCheck: boolean
  minAuthLevel: number
  enableOnebotAdminCheck: boolean
  enableWhiteListCheck: boolean
  userAuthWhiteList: string[]

  warningStages: {
    // type: 'mute' | 'recall' | 'kick'
    enableMute: boolean
    enableRecall: boolean
    enableKick: boolean
    muteDuration?: number
    warnMessage: string
  }[],
  maxWarnRejectThreshold: number,
  logQqGroupIdList: string[],
  logKookChannelIdList: string[],
  verboseSessionOutput: boolean,
  verboseConsoleOutput: boolean,
}

export const Config: Schema<Config> = Schema.intersect([
  Schema.object({
    version: Schema.string().disabled().default(pkg.version)
  }).description("版本号相关"),

  
  Schema.object({
    enableKoishiDbAuthCheck: Schema.boolean().default(false).description("是否启用koishi数据库权限校验"),
    minAuthLevel: Schema.number().min(0).max(4).step(1).default(3).description("最低权限等级, 建议3别动"),
    enableOnebotAdminCheck: Schema.boolean().default(true).description("是否启用onebot群主管理员校验"),
    enableWhiteListCheck: Schema.boolean().default(true).description("是否启用白名单校验"),
    userAuthWhiteList: Schema.array(String).role('tablea').default(["1830540513"]).description("白名单用户列表"),
  }).description("用户权限校验设置"),

  Schema.object({
    warningStages: Schema.array(
      Schema.object({
        // type: Schema.union(['mute', 'recall', 'kick']),
        enableMute: Schema.boolean().default(false),
        enableRecall: Schema.boolean().default(false),
        enableKick: Schema.boolean().default(false),
        muteDuration: Schema.number().min(0),
        warnMessage: Schema.string(),
      })
    ).role('table'),
    maxWarnRejectThreshold: Schema.number().default(5).description('最大警告次数门槛。 大于这个数值会自动拒绝入群'),
  }).description('警告阶段配置'),

  Schema.object({
    logQqGroupIdList: Schema.array(String).role('table').description("log的qq群列表"),
    logKookChannelIdList: Schema.array(String).role('table').description("log的kook频道列表"),
  }).description("log配置"),

  Schema.object({
    verboseSessionOutput: Schema.boolean().default(false).description('是否输出详细的会话信息'),
    verboseConsoleOutput: Schema.boolean().default(false).description('是否输出详细的控制台信息'),
  }).description('调试配置')
]);

declare module 'koishi' {
  interface Tables {
    warn: {
      platform: string
      userId: string
      guildId: string
      count: number
    }
  }
}


export function apply(ctx: Context, config: Config) {

    async function hasPermission(session: Session): Promise<boolean> {

    if ( config.enableKoishiDbAuthCheck ){
      const bindingEntries = await ctx.database.get('binding', { pid: session.userId });
      if ( bindingEntries && bindingEntries.length>0 ){
        const b0 = bindingEntries[0];
        const userEntries = await ctx.database.get('user', { id: b0.aid });
        if ( userEntries && userEntries.length>0 ){
          const u0 = userEntries[0];
          if ( u0.authority >= 3 ){
            return true;
          }
        }
      }
    }

    if ( config.enableOnebotAdminCheck ){
      const res = await session.bot.getGuildMember(session.guildId, session.userId);
      if (res.roles.includes("owner") || res.roles.includes("admin")) {
        return true;
      }
    }

    if ( config.enableWhiteListCheck ){
      if ( config.userAuthWhiteList.includes(session.userId) ){
        return true;
      }
    }

  }


  ctx.on('guild-member-request', async (session) => {
    const requestUser = await session.bot.getUser(session.userId);

    let requestMsg = ``;
    requestMsg += `=====有新的加群申请=====`;
    requestMsg += `\n\t申请人qq号: ${session.userId}`;
    requestMsg += `\n\t申请人昵称: ${requestUser.name}`;
    if ( config.verboseConsoleOutput )
      ctx.logger.info(requestMsg);

    requestMsg += `\n\t申请人头像: ${ h.image( requestUser.avatar )}`;
    if ( config.verboseSessionOutput )
      session.send(requestMsg);

      const targetKey = {
      platform: session.platform,
      userId: session.userId,
      guildId: session.guildId,
    };
    const [data] = await ctx.database.get('warn', targetKey);
    const count = data?.count || 0;

    ctx.logger.info(`[debug] session.toJson() = ${ JSON.stringify(session) }`)

    if ( count > config.maxWarnRejectThreshold ){
      await session.onebot._request('set_group_add_request', {
        flag: session.messageId,
        approve: false,
        reason: `警告次数已达上限，拒绝申请。`,
      })
    }

  })

  ctx.model.extend('warn', {
    platform: 'string',
    userId: 'string',
    guildId: 'string',
    count: { type: 'unsigned', initial: 0 }
  }, {
    primary: ['platform', 'userId', 'guildId'],
  })


  ctx.command(
    "warn", 
    "(警告某人并记录,撤回功能需要引用，否则就默认最新一条)\t用法:warn 艾特目标用户"
  )
  .action( async ({session, options}) => {
    if ( !await hasPermission(session) )
        return "你没有warn权限。"

    let at_user = null;
    for ( const e of session.event.message.elements ){
      if ( e.type === 'at'){
        at_user = e;
        break;
      }
    }
    if ( !at_user ){
      let errmsg = "[error]没有艾特用户。"
      await session.send(errmsg);
      ctx.logger.info(errmsg);
      return;
    }
    if ( at_user.attrs.id === session.bot.selfId ) {
      await session.send( h.quote(session.messageId) + `不能warn自己喵Ծ‸Ծ。`);
      return;
    }

    const targetUserId = at_user.attrs.id;
    const targetUserName = at_user.attrs.name;
    const targetPlatform = session.platform;
    const targetGuildId = session.guildId;

    const targetKey = { 
      platform: targetPlatform,
      userId: targetUserId,
      guildId: targetGuildId
    }

    const [warnData] = await ctx.database.get('warn', targetKey);
    const currentCount = warnData?.count || 0;

    let thisStage;
    let reachMaxWarn = false;
    if ( currentCount <= config.warningStages.length-1 ){
      thisStage = config.warningStages[currentCount];
    } else {
      reachMaxWarn = true;
      thisStage = config.warningStages[config.warningStages.length-1];
    }

    // let msg = `[警告 第${currentCount + 1}次] ${thisStage.warnMessage}`;
    const parsedWarnMessage = thisStage.warnMessage
      .replace(/\\n/g, '\n') // Replace \n with actual newline
      .replace(/\\t/g, '\t'); // Replace \t with actual tab

    let msg = `[警告 第${currentCount + 1}次]` + `${parsedWarnMessage}`;
    
    if ( reachMaxWarn ){
      msg += `[info] 已超出warnStage.length, 顶满格。当前次数：${currentCount}`;
    }

    if (thisStage.enableRecall) {
      // -----撤回-----
      let targetMsgId;
      if ( session.quote ){
        targetMsgId = session.quote.id;
        await session.bot.deleteMessage(session.channelId, targetMsgId);
      } else{
        // await session.send(`[error] 这次警告是撤回，但是没有引用消息`);
        msg += `\n[error] 这次警告是撤回，但是没有引用消息`;
      }
      // -----撤回-----
    }
    
    if (thisStage.enableMute) {
      // -----禁言-----
      await session.onebot._request('set_group_ban', {
        user_id: parseInt(targetUserId),
        group_id: parseInt(session.guildId),
        duration: thisStage.muteDuration || 60,
      });
      if ( !thisStage.muteDuration ){
        msg += `\n[error] 禁言时间未设置，默认禁言60秒。`;
      }
      // -----禁言-----
    }
    
    if (thisStage.enableKick) {
      // -----踢人-----
      await session.onebot._request('set_group_kick', {
        user_id: parseInt(targetUserId),
        group_id: parseInt(session.guildId),
        reject_add_request: false,
      });
      // -----踢人-----
    }

    await ctx.database.upsert('warn', [{
      ...targetKey,
      count: currentCount + 1,
    }]);
    // await session.send(msg);
    await session.send( h.text(msg) );

    let warnMsg = `=====warn记录=====\n\n`;

    warnMsg += `warn时间: \t${formatDate(new Date())}\n`;
    warnMsg += `warn群号: \t${session.guildId}\n`;
    const sessionGuild = await session.bot.getGuild(session.guildId);
    if ( sessionGuild )
      warnMsg += `warn群名: \t${sessionGuild.name}\n`;
    warnMsg += `------------------\n`;

    warnMsg += `被warn人qq号: \t${targetUserId}\n`;
    warnMsg += `被warn人qq名: \t${targetUserName}\n`;
    const targetUserAvatarUrl = (await session.bot.getUser(targetUserId, session.guildId)).avatar;
    const targerUserAvatarBase64_png_withHead = await resizeImageToBase64(ctx, targetUserAvatarUrl);
    warnMsg += `被warn人qq头像:`;
    warnMsg += h(
      'image',
      { url: targerUserAvatarBase64_png_withHead }
    )

    warnMsg += `被warn的消息: \t`;
    if ( session.quote ){
      const quoteContent = session.quote.content;
      warnMsg += quoteContent.length < 100 ?
        quoteContent :
        quoteContent.slice(0,100) + '(只显示前100字符，后省略......)';
    } else {
      warnMsg += '(无。warn的时候未进行指定消息引用)';
    }

    for ( const id of config.logQqGroupIdList ){
      try {
        await session.bot.sendMessage(id, warnMsg);
      } catch(err) {
        ctx.logger.error(`向QQ群 ${id}发送log失败: ${err}`);
      }
    }


    const kookBot = ctx.bots.find(bot => bot.platform === "kook");
    
    for ( const id of config.logKookChannelIdList ){
      try {
        await kookBot.sendMessage(id, warnMsg);
      } catch(err) {
        ctx.logger.error(`向kook频道 ${id}发送log失败: ${err}`);
      }
    }

  })



    // 1. warn.clear <@user>
  ctx.command("warn.clear", "\t(清除某人警告次数)\t\twarn.clear + 艾特指定人")
  .action(async ({ session }) => {
    if ( !await hasPermission(session) )
        return "你没有warn权限。"
    
    const at_user = session.event.message.elements.find(e => e.type === 'at');
    if (!at_user) {
      await session.send("[error] 请艾特要清除记录的用户。");
      return;
    }

    const targetKey = {
      platform: session.platform,
      userId: at_user.attrs.id,
      guildId: session.guildId,
    };

    await ctx.database.upsert('warn', [{
      ...targetKey,
      count: 0,
    }]);

    await session.send(`[info] 已清空 ${at_user.attrs.id} 的警告记录。`);
  });

  // 2. warn.set <count> <@user>
  ctx.command("warn.set <count:number>", "   \t(设置某个人的警告次数)\twarn.set + 次数 + 艾特目标用户 ")
  .action(async ({ session, args }) => {
    if ( !await hasPermission(session) )
        return "你没有warn权限。"

    const count = args[0];
    if (isNaN(count) || count < 0) {
      await session.send("[error] 请输入有效的警告次数（非负整数）。");
      return;
    }

    const at_user = session.event.message.elements.find(e => e.type === 'at');
    if (!at_user) {
      await session.send("[error] 请艾特要设置记录的用户。");
      return;
    }

    const targetKey = {
      platform: session.platform,
      userId: at_user.attrs.id,
      guildId: session.guildId,
    };

    await ctx.database.upsert('warn', [{
      ...targetKey,
      count,
    }]);

    await session.send(`[info] 已将 ${at_user.attrs.id} 的警告次数设置为 ${count}。`);
  });

  // 3. warn.query <@user>
  ctx.command("warn.query", "(查询某个人警告次数)\twarn.query + 艾特某个人 ")
  .action(async ({ session }) => {
    if ( !await hasPermission(session) )
        return "你没有warn权限。"

    const at_user = session.event.message.elements.find(e => e.type === 'at');
    if (!at_user) {
      await session.send("[error] 请艾特要查询记录的用户。");
      return;
    }

    const targetKey = {
      platform: session.platform,
      userId: at_user.attrs.id,
      guildId: session.guildId,
    };

    const [data] = await ctx.database.get('warn', targetKey);
    const count = data?.count || 0;

    await session.send(`[info] 用户 ${at_user.attrs.id} 的当前警告次数为 ${count}。`);
  });

  // 4. warn.list
  ctx.command("warn.list", "  \t(查询所有人警告次数)\twarn.list")
  .action(async ({ session }) => {
    if ( !await hasPermission(session) )
        return "你没有warn权限。"

    const records = await ctx.database.get('warn', {
      platform: session.platform,
      guildId: session.guildId,
    });

    let filtered = records.filter(r => r.count > 0);
    if (filtered.length === 0) {
      await session.send(`[info] 当前群内没有任何警告记录。`);
      return;
    }
    filtered.sort((a, b) => b.count - a.count);

    const groupInfoObj = await session.onebot.getGroupInfo(session.guildId);
    const groupAvatarUrl = `https://p.qlogo.cn/gh/${session.guildId}/${session.guildId}/640/`;
    const groupAvatarBase64_withHead = await resizeImageToBase64(ctx, groupAvatarUrl);

    let forwardMsg = '';

    const addMsgBlock = (authorId: string, authorName: string, contentStr: string) => {
        forwardMsg += `
          <message>
            <author ${authorId ? `id="${authorId}"` : ``} name="${authorName}"/>
            ${contentStr}
          </message>`;
    };

    const botSelfObj = await session.bot.getUser(session.bot.selfId, session.guildId);

    addMsgBlock(
      session.bot.selfId,
      botSelfObj.name,
      [
        `当前时间: \t ${new Date().toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' })}`,
        `${h.image(groupAvatarBase64_withHead)}`,
        `=========群聊信息=========`,
        `\t\t群名称: \t ${groupInfoObj.group_name}`,
        `\t\t群号: \t ${groupInfoObj.group_id}`,
        `\t\t成员数: \t ${groupInfoObj.member_count}/${groupInfoObj.max_member_count}`,
      ].join('\n')
    )

    for ( let i = 0; i < filtered.length; i++ ){
      const u = filtered[i];
      const uObj = await session.bot.getUser(u.userId, session.guildId);
      const groupMemberObj = session.onebot && await session.onebot.getGroupMemberInfo(session.guildId, u.userId);
      const uAvatarUrl = (await session.bot.getUser(u.userId, session.guildId)).avatar;
      const uAvatarBase64_withHead = await resizeImageToBase64(ctx, uAvatarUrl);

      addMsgBlock(
        u.userId,
        uObj.name,
        [
          `QQ号: \t ${u.userId}`,
          `QQ昵称: \t ${uObj.name}`,
          `群昵称: \t ${groupMemberObj.card || uObj.name}`,
          `${h.image(uAvatarBase64_withHead)}`,
          `.  ↑ 警告次数: \t ${u.count}`,
          `.  ↑ 警告时间: \t ${new Date().toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' })}`,
        ].join('\n')
      )
    }

    //包装成合并转发
    forwardMsg = `<message forward>\n` + forwardMsg + `</message>\n`;
    await session.send(forwardMsg);
  });

}



declare module 'koishi' {
  interface Context {
    warn: WarnService;
  }
}


// 定义 WarnService 类，封装核心逻辑
class WarnService extends Service {
  constructor(ctx: Context) {
    super(ctx, 'warn', true); // 'warn' 是服务名称，true 表示立即注册
  }

  // 暴露给其他插件调用的核心方法
  // 这个方法接受平台、群ID和用户ID，并执行警告逻辑
  async triggerWarn(platform: string, guildId: string, userId: string, messageId?: string) {
    const ctx = this.ctx; // 获取服务实例所在的上下文
    const database = ctx.database; // 访问数据库服务

    // 从数据库中获取警告次数
    const targetKey = { 
      platform: platform,
      userId: userId,
      guildId: guildId
    };
    const [warnData] = await database.get('warn', targetKey);
    const currentCount = warnData?.count || 0;

    // 假设 warnStages 和 maxWarnRejectThreshold 等配置项可以从主插件的 config 中获取
    // 你需要确保这些配置能被服务访问到，比如在服务实例中存储 config
    const config = (this as any).ctx.root.config['progressive-warn'];

    // 接下来是原先 command.action 中的核心逻辑
    // ...（将你原先在 .action() 中处理警告的逻辑复制到这里）...
    
    // 假设要执行禁言操作
    // 注意：这里的 bot 需要根据平台和群ID来获取
    const bot = ctx.bots.find(b => b.platform === platform);
    if (bot) {
      // 这里的逻辑需要根据不同的平台API进行适配，目前你的代码主要针对 onebot
      // await bot.setGroupBan(guildId, userId, duration);
      // await bot.setGroupKick(guildId, userId);
      
      // ... 警告处理逻辑 ...
      
      // 更新数据库
      await database.upsert('warn', [{
        ...targetKey,
        count: currentCount + 1,
      }]);

      // 还可以返回一个结果，比如警告成功与否
      return { success: true, newCount: currentCount + 1 };
    } else {
      return { success: false, error: `未找到平台 ${platform} 的 bot 实例。` };
    }
  }
}
